home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- Cambridge, MA 02139, USA. */
-
- #include <ansidecl.h>
-
- #ifndef __GNUC__
- #error This file uses GNU C extensions; you must compile with GCC.
- #endif
-
- /* Get the definition of `struct sigcontext'. */
- #define KERNEL
- #define sigvec sun_sigvec
- #define sigstack sun_sigstack
- #define sigcontext sun_sigcontext
- #include "/usr/include/sys/signal.h"
- #undef sigvec
- #undef sigstack
- #undef sigcontext
- #undef NSIG
- #undef SIGABRT
- #undef SIGCLD
- #undef SV_ONSTACK
- #undef SV_RESETHAND
- #undef SV_INTERRUPT
- #undef SA_ONSTACK
- #undef SA_NOCLDSTOP
- #undef SIG_ERR
- #undef SIG_DFL
- #undef SIG_IGN
- #undef sigmask
- #undef SIG_BLOCK
- #undef SIG_UNBLOCK
- #undef SIG_SETMASK
-
- #include <signal.h>
- #include <stddef.h>
- #include <errno.h>
-
- /* Defined in __sigvec.S. */
- extern int EXFUN(__raw_sigvec, (int sig, CONST struct sigvec *vec,
- struct sigvec *ovec));
-
- /* User-specified signal handlers. */
- #define mytramp 1
- #ifdef mytramp
- static __sighandler_t handlers[NSIG];
- #else
- #define handlers _sigfunc
- extern __sighandler_t _sigfunc[];
- #endif
-
- #if mytramp
-
- /* Handler for all signals that are handled by a user-specified function.
- Saves and restores the general regs %g2-%g7, the %y register, and
- all the FPU regs (including %fsr), around calling the user's handler. */
- static void
- DEFUN(trampoline, (sig), int sig)
- {
- /* We use `double' and `long long int' so `std' (store doubleword) insns,
- which might be faster than single-word stores, will be generated. */
- register double f0 asm("%f0");
- register double f2 asm("%f2");
- register double f4 asm("%f4");
- register double f6 asm("%f6");
- register double f8 asm("%f8");
- register double f10 asm("%f10");
- register double f12 asm("%f12");
- register double f14 asm("%f14");
- register double f16 asm("%f16");
- register double f18 asm("%f18");
- register double f20 asm("%f20");
- register double f22 asm("%f22");
- register double f24 asm("%f24");
- register double f26 asm("%f26");
- register double f28 asm("%f28");
- register double f30 asm("%f30");
- register long long int g2 asm("%g2");
- register long long int g4 asm("%g4");
- register long long int g6 asm("%g6");
- register int *fp asm("%fp");
-
- int code;
- register struct sigcontext *context asm("%i0"); /* See end of fn. */
- PTR addr;
- int y;
- double fpsave[16];
- int fsr;
- int savefpu;
- long long int glsave[3];
-
- /* SIG isn't really passed as an arg.
- The args to the signal handler are at fp[16..19]. */
- sig = fp[16];
- code = fp[17];
- context = (struct sigcontext *) fp[18];
- addr = (PTR) fp[19];
-
- /* Save the Y register. */
- asm("rd %%y, %0" : "=r" (y));
-
- /* Save the FPU regs if the FPU enable bit is set in the PSR,
- and the signal isn't an FP exception. */
- savefpu = (context->sc_psr & 0x1000) && sig != SIGFPE;
- if (savefpu)
- {
- fpsave[0] = f0;
- fpsave[1] = f2;
- fpsave[2] = f4;
- fpsave[3] = f6;
- fpsave[4] = f8;
- fpsave[5] = f10;
- fpsave[6] = f12;
- fpsave[7] = f14;
- fpsave[8] = f16;
- fpsave[9] = f18;
- fpsave[10] = f20;
- fpsave[11] = f22;
- fpsave[12] = f24;
- fpsave[13] = f26;
- fpsave[14] = f28;
- fpsave[15] = f30;
-
- /* Force it into a stack slot so the asm won't barf. Sigh. */
- (void) &fsr;
- asm("st %%fsr, %0" : "=m" (fsr));
- }
-
- /* Save the global registers (except for %g1, which is a scratch reg). */
- glsave[0] = g2;
- glsave[1] = g4;
- glsave[2] = g6;
-
- /* Call the user's handler. */
- (*((void EXFUN((*), (int sig, int code, struct sigcontext *context,
- PTR addr))) handlers[sig]))
- (sig, code, context, addr);
-
- /* Restore the Y register. */
- asm("mov %0, %%y" : : "r" (y));
-
- if (savefpu)
- {
- /* Restore the FPU regs. */
- f0 = fpsave[0];
- f2 = fpsave[1];
- f4 = fpsave[2];
- f6 = fpsave[3];
- f8 = fpsave[4];
- f10 = fpsave[5];
- f12 = fpsave[6];
- f14 = fpsave[7];
- f16 = fpsave[8];
- f18 = fpsave[9];
- f20 = fpsave[10];
- f22 = fpsave[11];
- f24 = fpsave[12];
- f26 = fpsave[13];
- f28 = fpsave[14];
- f30 = fpsave[15];
-
- asm("ld %0, %%fsr" : : "m" (fsr));
- }
-
- /* Restore the globals. */
- g2 = glsave[0];
- g4 = glsave[1];
- g6 = glsave[2];
-
- /* Unwind a frame, and do a "sigcleanup" system call.
- The system call apparently does a return.
- I don't know what it's for. Ask Sun. */
- asm("restore %%g0, 139, %%g1\n"
- "ta 0\n"
- "! this should be i0: %0" /* Useless insn that will never be executed, */
- /* here to make the compiler happy. */
- : /* No outputs. */ :
- /* CONTEXT is bound to %i0. We reference it as an input here to make
- sure the compiler considers it live at this point, and preserves
- the value in that register. The restore makes %i0 become %o0, the
- argument to the system call. */
- "r" (context));
- }
- #endif
-
- int
- DEFUN(__sigvec, (sig, vec, ovec),
- int sig AND CONST struct sigvec *vec AND struct sigvec *ovec)
- {
- #ifndef mytramp
- extern void _sigtramp (int);
- #define trampoline _sigtramp
- #endif
- struct sigvec myvec;
- int mask;
- __sighandler_t ohandler;
-
- if (sig <= 0 || sig >= NSIG)
- {
- errno = EINVAL;
- return -1;
- }
-
- mask = __sigblock(sigmask(sig));
-
- ohandler = handlers[sig];
-
- if (vec != NULL &&
- vec->sv_handler != SIG_IGN && vec->sv_handler != SIG_DFL)
- {
- handlers[sig] = vec->sv_handler;
- myvec = *vec;
- myvec.sv_handler = trampoline;
- vec = &myvec;
- }
-
- if (__raw_sigvec(sig, vec, ovec) < 0)
- {
- int save = errno;
- (void) __sigsetmask(mask);
- errno = save;
- return -1;
- }
-
- if (ovec != NULL && ovec->sv_handler == trampoline)
- ovec->sv_handler = ohandler;
-
- (void) __sigsetmask(mask);
-
- return 0;
- }
-